package com.aliyun.heiyu.powermaster.server.manager;

import com.aliyun.heiyu.common.util.DateUtil;
import com.aliyun.heiyu.common.util.StringUtil;
import com.aliyun.heiyu.common.util.TimeConvertUtil;
import com.aliyun.heiyu.powermaster.proto.DeviceInfo;
import com.aliyun.heiyu.powermaster.proto.StrategyAction;
import com.aliyun.heiyu.powermaster.proto.StrategyControlHistory;
import com.aliyun.heiyu.powermaster.proto.StrategyDetail;
import com.aliyun.heiyu.powermaster.server.dao.Strategy2DeviceDao;
import com.aliyun.heiyu.powermaster.server.dao.StrategyActionDao;
import com.aliyun.heiyu.powermaster.server.dao.StrategyActionHistoryDao;
import com.aliyun.heiyu.powermaster.server.dao.StrategyDao;
import com.aliyun.heiyu.powermaster.server.dao.entity.*;
import com.aliyun.heiyu.powermaster.server.dao.impl.Strategy2DeviceImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.StrategyActionHistoryImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.StrategyActionImpl;
import com.aliyun.heiyu.powermaster.server.dao.impl.StrategyImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StrategyManagerBak implements StrategyManagerInterface {
    private static final Logger logger = LoggerFactory.getLogger(StrategyManagerBak.class);

    private StrategyDao strategyDao;
    private StrategyActionDao strategyActionDao;
    private Strategy2DeviceDao strategy2DeviceDao;
    private StrategyActionHistoryDao actionHistoryDao;
    private DeviceManager deviceManager;

    private static volatile StrategyManagerBak instance;

    public static StrategyManagerBak getInstance() {
            synchronized (StrategyManagerBak.class) {
                if (instance == null) {
                    instance = new StrategyManagerBak();
                }
            }

        return instance;
    }

    private StrategyManagerBak() {
        this.strategyDao = new StrategyImpl();
        this.strategyActionDao = new StrategyActionImpl();
        this.strategy2DeviceDao = new Strategy2DeviceImpl();
        this.actionHistoryDao = new StrategyActionHistoryImpl();
        deviceManager = DeviceManagerImpl.getInstance();
    }

    /**
     * 新增一条策略
     * @param strategyDetail
     * @return
     */
    //todo 如果多进程在设备详情编辑策略，会出现重复数据
    public boolean insert(StrategyDetail strategyDetail) {
        boolean ret = true;
        //新增策略
        StrategyEntity strategyEntity = detailToEntity(strategyDetail);
        Integer insertID = strategyDao.insert(strategyEntity);
        //新增策略动作
        List<StrategyAction> strategyActionsList = strategyDetail.getStrategyActionsList();
        ret &= updateStrategyActions(insertID, strategyActionsList);
        return ret;
    }

    /**
     * 策略的部分更新: 两种情况：第一个只更新switchOn，第二种更新除switchOn之外的其他的所有
     */
    //todo 如果多进程在设备详情编辑策略，会出现重复数据
    public boolean patch(StrategyDetail strategyDetail) {
        boolean ret = true;
        StrategyEntity strategyEntity = detailToEntity(strategyDetail);
        String strategyName = strategyDetail.getStrategyName();
        //更新switchOn: 根据strategyName是否有值来判断是否更新
        if (strategyName == null || strategyName.isEmpty()) {
            //更新策略开关
            ret &= strategyDao.updateSwitch(strategyEntity);
            return ret;
        }
        //更新策略
        ret &= strategyDao.update(strategyEntity);
        if(!ret){
            return ret;
        }
        if("1".equals(strategyDetail.getType())){
            return ret;
        }
        //更新策略动作（删除再添加）
        List<StrategyAction> strategyActionsList = strategyDetail.getStrategyActionsList();
        ret &= updateStrategyActions(strategyDetail.getStrategyID(), strategyActionsList);
        return ret;
    }

    /**
     * 删除某条策略
     */
    public boolean delete(String[] ids) {
        //同时删除三个表
        boolean ret = strategyDao.delete(ids);
        ret &= strategyActionDao.deleteByStrategyIDs(ids);
        ret &= strategy2DeviceDao.deleteByStrategyIDs(ids);
        return ret;
    }

    public int getCountByCondition(String str, String type){
        return strategyDao.getCountByCondition(str,type);
    }

    public List<StrategyDetail> getByCondition(String str, String type){
        ArrayList<StrategyDetail> list = new ArrayList<>();
        List<StrategyEntity> entities = strategyDao.findByCondition(str, type);
        if(entities == null){
            return list;
        }
        return convertToStrategyDetail(entities);
    }

    public List<StrategyDetail> getByCondition(String str, String type, int start, int size){
        ArrayList<StrategyDetail> list = new ArrayList<>();
        List<StrategyEntity> entities = strategyDao.findByCondition(str, type, start, size);
        if(entities == null){
            return list;
        }
        return convertToStrategyDetail(entities);
    }

    public StrategyDetail getStrategy(int id) {
        StrategyEntity entity = strategyDao.findOne(id);
        if (null == entity) {
            return null;
        }
        List<StrategyEntity> list = new ArrayList<>(1);
        list.add(entity);
        List<StrategyDetail> strategyDetailList = convertToStrategyDetail(list);
        return strategyDetailList.get(0);
    }

    public boolean deleteDevices(Object[] deviceList){
        if(deviceList == null || deviceList.length == 0){
            return true;
        }
        return strategy2DeviceDao.delete(deviceList);
    }

    @Override
    public boolean deleteDevices(int strategyID, Object[] deviceList) {
        if(deviceList == null || deviceList.length == 0){
            return true;
        }
        return strategy2DeviceDao.delete(strategyID, deviceList);
    }

    @Override
    public boolean deleteStrategyDevices(int strategyID, Object[] deviceList) {
        if(deviceList == null || deviceList.length == 0){
            return true;
        }
        return strategy2DeviceDao.deleteStrategyIdOrInDevices(strategyID, deviceList);
    }

    public boolean insertDevice(Strategy2DeviceEntity entity){
        return strategy2DeviceDao.insert(entity);
    }

    public int getCountHistoryByCondition(String deviceId){
        return actionHistoryDao.count(deviceId);
    }

    public List<StrategyControlHistory> getHistoryByCondition(String deviceId){
        List<StrategyActionHistoryEntity> entityList = actionHistoryDao.getByCondition(deviceId);
        return toStrategyControlHistory(entityList);
    }

    public List<StrategyControlHistory> getHistoryByCondition(String deviceId, int start, int size){
        List<StrategyActionHistoryEntity> entityList = actionHistoryDao.getByCondition(deviceId, start, size);
        return toStrategyControlHistory(entityList);
    }

    public StrategyDetail getStrategyDetailByDeviceId(String deviceID){
        StrategyEntity entity = strategyDao.findOneByDevice(deviceID);
        if(entity == null){
            return null;
        }
        return convertToStrategyDetail(Arrays.asList(entity)).get(0);
    }

    public StrategyEntity getStrategyByDeviceId(String sn) {
        return strategyDao.findOneByDevice(sn);
    }

    public boolean virtyStrategyIdExit(int id){
        StrategyEntity strategyEntity = strategyDao.findOne(id);
        if(strategyEntity == null){
            return false;
        }
        return true;
    }

    public boolean virtyStrategyNameExit(String name){
        StrategyEntity strategyEntity = strategyDao.findByName(name);
        if(strategyEntity == null){
            return false;
        }
        return true;
    }

    public boolean insertActionHistory(StrategyActionHistoryEntity entity) {
        boolean ret = actionHistoryDao.insert(entity);
        return ret;
    }

    public List<StrategyDetail> getAllStrategiesOfOn() {
        List<StrategyEntity> strategyEntities = strategyDao.findAllOfOn();
        List<StrategyDetail> strategyDetailList = convertToStrategyDetail(strategyEntities);
        return strategyDetailList;
    }

    @Override
    public Strategy2DeviceEntity findByDeviceId(String sn) {
        return strategy2DeviceDao.findByDeviceId(sn);
    }

    private List<StrategyControlHistory> toStrategyControlHistory(List<StrategyActionHistoryEntity> entityList){
        List<StrategyControlHistory> list = new ArrayList<>();
        if(null == entityList || entityList.size() == 0){
            return list;
        }
        list = entityList.stream().map(o -> toStrategyControlHistory(o)).collect(Collectors.toList());
        return list;
    }

    private StrategyControlHistory toStrategyControlHistory(StrategyActionHistoryEntity entity){
        StrategyControlHistory.Builder builder = StrategyControlHistory.newBuilder();
        String controlName = "";
        if("power_off".equals(entity.getActionName())){
            if(entity.getSwitchOn()){
                controlName = "加入低功耗缓存池";
            } else {
                controlName = "移出低功耗缓存池";
            }
        } else if("shut_down".equals(entity.getActionName())){
            if(entity.getSwitchOn()){
                controlName = "执行关机/休眠";
            } else {
                controlName = "执行开机/唤醒";
            }
        } else {
            controlName = (entity.getSwitchOn() ? "开启" : "关闭") + entity.getActionName();
        }
        builder.setControlName(controlName);
        Timestamp time = entity.getTime();
        String timeStr = DateUtil.stamp2String(time, new SimpleDateFormat(TimeConvertUtil.DATETIME_PATTERN));
        builder.setControlTime(timeStr);
        List<String> statusList = getActionStatus(entity.getDeviceID(), time);
        builder.addAllStatus(statusList);
        return builder.build();
    }

    private StrategyActionEntity toStrategyActionEntity(int strategyID, StrategyAction strategyAction){
        StrategyActionEntity actionEntity = new StrategyActionEntity();
        actionEntity.setStrategyID(strategyID);
        actionEntity.setActionName(strategyAction.getActionName());
        actionEntity.setFmin(strategyAction.getFmin());
        actionEntity.setCapType(strategyAction.getCapType());
        actionEntity.setCapTo(strategyAction.getCapTo());
        StrategyAction.ActionCondition actionCondition = strategyAction.getActionCondition();
        actionEntity.setState(actionCondition.getState());
        actionEntity.setMinCPUUsage(actionCondition.getMinCPUUsage());
        actionEntity.setMaxCPUUsage(actionCondition.getMaxCPUUsage());
        actionEntity.setMinPower(actionCondition.getMinPower());
        actionEntity.setMaxPower(actionCondition.getMaxPower());
        actionEntity.setStartTime(actionCondition.getStartTime());
        actionEntity.setEndTime(actionCondition.getEndTime());
        return actionEntity;
    }

    /**
     * 更新策略动作：统一删除旧的策略动作，然后新增新的策略动作
     */
    private boolean updateStrategyActions(Integer strategyID, List<StrategyAction> strategyActionsList) {
        boolean ret = true;
        ret &= strategyActionDao.deleteByStrategyId(strategyID);
        if(!ret){
            return ret;
        }

        for (StrategyAction strategyAction : strategyActionsList) {
            StrategyActionEntity actionEntity = toStrategyActionEntity(strategyID,strategyAction);
            ret &= strategyActionDao.insert(actionEntity);
            if(!ret){
                return ret;
            }
        }
        return ret;
    }

    private StrategyEntity detailToEntity(StrategyDetail strategyDetail){
        StrategyEntity strategyEntity = new StrategyEntity();
        strategyEntity.setStrategyName(strategyDetail.getStrategyName());
        strategyEntity.setSwitchOn(strategyDetail.getSwitchOn());
        int type = strategyDetail.getType();
        strategyEntity.setType(type);
        strategyEntity.setControlLevel(strategyDetail.getControlLevel());
        strategyEntity.setBusiness(strategyDetail.getBusiness());
        Timestamp nowTime = new Timestamp(System.currentTimeMillis());
        strategyEntity.setModifiedTime(nowTime);
        strategyEntity.setStrategyID(strategyDetail.getStrategyID());
        return strategyEntity;
    }

    private List<String> getActionStatus(String deviceId, Timestamp time){
        List<String> actionStatus = actionHistoryDao.getActionStatus(deviceId, time);
        if(actionStatus == null){
            return new ArrayList<String>();
        }
        return actionStatus;
    }

    /**
     * 根据策略ID获取该策略下的所有设备的设备信息
     */
    private List<DeviceInfo> getDeviceInfosByStrategyID(Integer strategyID) {
        List<DeviceInfo> deviceInfos = new ArrayList<>();
        List<Strategy2DeviceEntity> entityList = strategy2DeviceDao.findByStrategyID(strategyID);
        for (Strategy2DeviceEntity entity : entityList) {
            String deviceID = entity.getDeviceID();
            DeviceCommonEntity oneDeviceCommon = deviceManager.findOneDeviceCommon(deviceID);
            if(null==oneDeviceCommon){
                continue;
            }
            DeviceInfo.Builder builder = DeviceInfo.newBuilder();
            if(!StringUtil.isEmpty(oneDeviceCommon.getIp())){
                builder.setIp(oneDeviceCommon.getIp());
            }
            builder.setEquipmentNumber(deviceID);
            builder.setDeviceType(oneDeviceCommon.getType());
            deviceInfos.add(builder.build());
        }
        return deviceInfos;
    }

    /**
     * 将StrategyEntity列表转化为StrategyDetail列表
     */
    private List<StrategyDetail> convertToStrategyDetail(List<StrategyEntity> strategyEntities) {
        List<StrategyDetail> strategyDetailList = new ArrayList<>();
        if (null == strategyEntities || strategyEntities.size() == 0) {
            return strategyDetailList;
        }
        List<StrategyActionEntity> actionEntities = strategyActionDao.findAll();

        for (StrategyEntity strategyEntity : strategyEntities) {
            StrategyDetail.Builder builder = StrategyDetail.newBuilder();
            builder.setStrategyID(strategyEntity.getStrategyID()==null?0:strategyEntity.getStrategyID());
            builder.setStrategyName(strategyEntity.getStrategyName()==null?"":strategyEntity.getStrategyName());
            builder.setSwitchOn(strategyEntity.getSwitchOn());
            int type = strategyEntity.getType();
            String controlLevel = "0";
            builder.setType(type);
            if (strategyEntity.getBusiness() != null) {
                builder.setBusiness(strategyEntity.getBusiness());
            }
            if (strategyEntity.getControlLevel() != null) {
                controlLevel = strategyEntity.getControlLevel();
            }
            builder.setControlLevel(controlLevel);
            long usedTime = (System.currentTimeMillis() - strategyEntity.getModifiedTime().getTime()) / 1000;
            builder.setUsedTime(usedTime);
            List<StrategyAction> actionList = new ArrayList<>();
            //type = 1 不加动作
            for (StrategyActionEntity actionEntity : actionEntities) {
                if (strategyEntity.getStrategyID().equals(actionEntity.getStrategyID())) {
                    StrategyAction.Builder builder2 = StrategyAction.newBuilder();
                    builder2.setActionName(actionEntity.getActionName()==null?"":actionEntity.getActionName());
                    builder2.setFmin(actionEntity.getFmin()==null?"":actionEntity.getFmin());
                    builder2.setCapTo(actionEntity.getCapTo()==null?"":actionEntity.getCapTo());
                    builder2.setCapType(actionEntity.getCapType()==null?"":actionEntity.getCapType());
                    StrategyAction.ActionCondition.Builder builder3 = StrategyAction.ActionCondition.newBuilder();
                    builder3.setState(actionEntity.getState()==null?"":actionEntity.getState());
                    builder3.setMaxCPUUsage(actionEntity.getMaxCPUUsage()==null?"":actionEntity.getMaxCPUUsage());
                    builder3.setMinCPUUsage(actionEntity.getMinCPUUsage()==null?"":actionEntity.getMinCPUUsage());
                    builder3.setMaxPower(actionEntity.getMaxPower()==null?"":actionEntity.getMaxPower());
                    builder3.setMinPower(actionEntity.getMinPower()==null?"":actionEntity.getMinPower());
                    builder3.setStartTime(actionEntity.getStartTime()==null?"":actionEntity.getStartTime());
                    builder3.setEndTime(actionEntity.getEndTime()==null?"":actionEntity.getEndTime());
                    builder2.setActionCondition(builder3);
                    actionList.add(builder2.build());
                }
            }
            builder.addAllStrategyActions(actionList);
            List<DeviceInfo> deviceInfos = getDeviceInfosByStrategyID(strategyEntity.getStrategyID());
            builder.addAllDeviceInfos(deviceInfos);
            strategyDetailList.add(builder.build());
        }
        return strategyDetailList;
    }

    public int getAIStrategyID() {
        return 1;
    }

    public List<StrategyDetail> getAllStrategies() {
        List<StrategyEntity> strategyEntities = strategyDao.findAll();
        List<StrategyDetail> strategyDetailList = convertToStrategyDetail(strategyEntities);
        return strategyDetailList;
    }

    public List<StrategyDetail> getAllAutoStrategiesOfOn() {
        List<StrategyEntity> strategyEntities = strategyDao.findAllAutoOfOn();
        List<StrategyDetail> strategyDetailList = convertToStrategyDetail(strategyEntities);
        return strategyDetailList;
    }
    @Override
    public List<StrategyDetail> getAllStrategiesOfOn1() {
        return null;
    }

}
